iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 25
0
Software Development

Ruby 研究 30 天系列 第 25

Day 24 - Super

  • 分享至 

  • xImage
  •  

Super

可以在繼承鏈上呼叫 ” 最接近的上層 “ 的同名方法,而若是找不到符合的方法則會產生 NoMethodError exception 。聽起來很單純,但其實這關係到我們在 Day 16 談過的「方法的呼叫」,同名的方法很可能不止一個,尤其當你學會 Ruby,最終總會來到實作階段,在 Rails 裡大量用到的繼承、方法調用的技巧。

在這裡先記得兩個準則:「後進先出」,以及「有彎先轉」。

module Mod_A
  def method
    puts "from Mod_A"
  end
end

module Mod_B
  def method
    puts "from Mod_B"
  end
end

class SuperKlass
  def method
    puts "from SuperKlass"
  end
end

class Klass < SuperKlass
  include Mod_A
  include Mod_B

  def method
    puts "from Klass"
    super
  end
end

obj = Klass.new
obj.method

# 印出以下內容
# from Klass
# from Mod_B

接著要回到昨天的話題,昨天在最後介紹了 Catch-All Argument ,單用一個 * 將所有的引數抓取,但抓取後不能自己操作,由於不能自己操作,所以我們會用 super 這個關鍵字讓繼承練的上層來代勞。

在之前的介紹中大家應該都知道了 Ruby 能省則省的小括號,但也有某些狀況省略不會得到你預期的結果,對於 super 這個方法就是個典型的例子, supersuper()可是兩件事情:

class Animal
  def food(breakfast, lunch, dinner)
    puts "#{breakfast}是一個好的開始 \n#{lunch}用來補充能量 #{dinner}可以讓我做個好夢 "
  end
end
class Dog < Animal
  def food(*)
    puts "汪汪汪"
    super
  end
end
husky = Dog.new
husky.food("牛排", "罐罐", "餅乾")

# 印出以下內容
# 汪汪汪
# 牛排是一個好的開始
# 罐罐用來補充能量 餅乾可以讓我做個好夢

super 會將子層同名方法後的引數往上層的方法傳遞,如上例將 food 方法後的引數往上傳,而這邊使用 Catch-All Argument ,若是上層方法參數數量有改變,下層也不需更動。

super() 則是可以自由選擇傳哪些引數上去,所以當裡面沒有填參數時,當然就不會傳遞任何引數。

class Animal
  def food(breakfast, lunch, dinner)
    puts "#{breakfast}是一個好的開始 \n#{lunch}用來補充能量 #{dinner}可以讓我做個好夢 "
  end
end
class Dog < Animal
  def food(breakfast, lunch, dinner, guilt)
    puts "汪汪汪"
    super(breakfast, lunch, dinner)
    puts "我還可以吃#{guilt}!!!"
  end
end
husky = Dog.new
husky.food("牛排", "罐罐", "餅乾", "更多餅乾")

# 印出
# 汪汪汪
# 牛排是一個好的開始 
# 罐罐用來補充能量 餅乾可以讓我做個好夢 
# 我還可以吃更多餅乾!!!

Initialize

這邊再補充一下,在類別裡我們如果要初始化,只能用 initialize 這個方法,那在同名方法中,想必它的發生率會最高,想像一下如果你今天繼承後想要擁有自己初始化的結果,同時也想要父類別的結果,當然你可以說我全部覆寫一次,覆寫最大,但你要記得維持乾燥這件事,「Don't repeat yourself」。

class Parent
  def initialize (name)
    @name = name
  end
end
 
class Child < Parent
  def initialize (age)
    @age = age
  end
end

這時你可以用 super 來調用。

class Child < Parent
  def initialize (name, age)
    super(name)
    @age = age
  end
end

此文同步刊登於CJ-Han的網站


上一篇
Day 23 - 引數與參數 下篇
下一篇
Day 25 - 正規表示式
系列文
Ruby 研究 30 天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言